package com.villaday.idf.base.broadcast;


import androidx.annotation.NonNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;


/**
 * 用RxJava实现EventBus
 */
public class RxBus {
    private static RxBus instance;
    private ConcurrentHashMap<Object, List<Subject>> subjectMapper=new ConcurrentHashMap<>();

    public static synchronized RxBus getInstance(){
        if (instance==null){
            instance=new RxBus();
        }
        return instance;
    }

    private RxBus(){}

    /**
     * 订阅事件源
     */
    public RxBus onEvent(Observable<?> mObservable, Consumer<Object> mAction1){
        mObservable.observeOn(AndroidSchedulers.mainThread()).subscribe(mAction1, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                throwable.printStackTrace();
            }
        });
        return getInstance();
    }

    /**
     * 注册事件源
     */
    public <T> Observable<T> register(@NonNull Object tag){
        List<Subject> subjectList=subjectMapper.get(tag);
        if (subjectList==null){
            subjectList=new ArrayList<Subject>();
            subjectMapper.put(tag,subjectList);
        }
        Subject<T> subject;
        subjectList.add(subject= PublishSubject.<T>create());
        return subject;
    }

    public void unregister(@NonNull Object tag){
        List<Subject> subjects=subjectMapper.get(tag);
        if (subjects!=null){
            subjectMapper.remove(tag);
        }
    }

    /**
     * 取消监听
     */
    public RxBus unregister(@NonNull Object tag,@NonNull Observable<?> observable){
        if (observable==null){
            return getInstance();
        }
        List<Subject> subjects=subjectMapper.get(tag);
        if (subjects!=null){
            subjects.remove(observable);
            if (isEmpty(subjects)){
                subjectMapper.remove(tag);
            }
        }
        return getInstance();
    }

    public void post(@NonNull Object content){
        post(content.getClass().getName(),content);
    }

    /**
     * 触发事件
     */
    public void post(@NonNull Object tag,@NonNull Object content){
        List<Subject> subjectList=subjectMapper.get(tag);
        if (!isEmpty(subjectList)){
            for (Subject subject:subjectList){
                subject.onNext(content);
            }
        }
    }

    public static boolean isEmpty(Collection<Subject> collection){
        return collection==null||collection.isEmpty();
    }
}
